<?php


namespace app\admin\ctrl;


class UploadCtrl
{
    /**
     * 分片上传测试
     * 最优方案：根据浏览器支持的最大并发数 n ，把文件分片成 n 份
     * 获取服务器支持最大上传大小
     *（1）nginx中添加client_max_body_size和client_body_buffer_size
     *（2）php.ini添加post_max_size和upload_max_filesize
     * @return void
     */
    public function getUpload()
    {
        $tempDir = ROOT . "public/upload/";
        $post = $_POST;
        $flag = intval($post["flag"]);
        $filename = trim($_POST["filename"]);
        $redis = redis();
        if ($flag == 0) { //上传分片
            $file = $_FILES["file"];
            if (!$redis->get($filename)) {
                debugLog('上传开始：' . $filename);
                $redis->set($filename, time());
            }
            $tmpFilename = $_POST["tempFilename"];
            if (!file_exists($tempDir)) {
                mkdir($tempDir, 0755, true);
            }
            $fileInfo = move_uploaded_file($file['tmp_name'], $tempDir . $tmpFilename);
            if ($fileInfo) { // 把分片的文件保存在了临时目录中，返回有点简单，可以根据需求返回相应的数据
                return_success(['error' => 0]);
            }
            return_success(['error' => 1]);
        } elseif ($flag == 1) { // 合并分片
            // glob对括号不起作用
            $filename2 = str_replace('[', '\[', $filename);
            $filename2 = str_replace(']', '\]', $filename2);
            $filename2 = str_replace('\[', '[[]', $filename2);
            $filename2 = str_replace('\]', '[]]', $filename2);

            // 通过文件名的字符串匹配，找上所有的分片，返回一个文件路径的数组，这里的*是一个通配符，将所有的文件名中包含的$filename的文件都找到
            $fileArr = glob($tempDir . "*_" . $filename2);

            // 说明一下，$fileArr中的数组的顺序不是我们想要的，所以我们新建一个数组来整理一下顺序
            $newFileArr = [];
            foreach ($fileArr as $f) {
                // js前端把文件的名称前加了'序号+_'，以下划线来分开并把序号写在key中
                $fileBaseName = basename($f); // $f是一个个的路径，这里使用basename得到文件名
                $fileBaseNameSplit = explode("_", $fileBaseName); // 通过下划线分割文件名
                $newFileArr[$fileBaseNameSplit[0]] = $f; // 构造了一个新的数组，其中数组的key就是顺序号，数组的值就是分片文件的路径
            }

            // 删除原件
            $newFilename = $tempDir . $filename;
            if (file_exists($newFilename)) {
                unlink($newFilename);
            }

            // 开始使用for循环来组装
            $num = count($newFileArr);
            for ($i = 1; $i <= $num; $i++) {
                file_put_contents($newFilename, file_get_contents($newFileArr[$i]), FILE_APPEND);
            }

            $start = $redis->get($filename);
            $redis->del($filename);
            $run = time() - $start;
            debugLog("上传完成：$filename - 耗时： $run");

            // 删除临时文件中的分片文件，这里可以使用try catch来判断是否有错误
            foreach ($newFileArr as $fi) {
                unlink($fi);
            }
            // 最后给前端返回保存的文件名就可以
            return_success(['length' => $num, 'run' => $run]);
        }
    }
}